package org.javahispano.javacup.tacticas_aceptadas.Pencerval.com.viavansi.javacup.movimiento;

import java.util.List;

import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;

import org.javahispano.javacup.tacticas_aceptadas.Pencerval.com.viavansi.javacup.alineaciones.Posiciones;
import org.javahispano.javacup.tacticas_aceptadas.Pencerval.com.viavansi.javacup.detallejugadores.JugadorProImplementation;
import org.javahispano.javacup.tacticas_aceptadas.Pencerval.com.viavansi.javacup.detallejugadores.JugadorProImplementationFactory;




public class Posicionamiento {

	static boolean controlo=true;
	
	static boolean ultimoPaseMio=false;
	static boolean ultimoPaseSuyo=false;
	
	public static void posicionRelativa(SituacionPartido sp,
			List<Comando> comandos) {
		if(sp.puedenRematarRival().length>0){
			ultimoPaseMio=false;
			ultimoPaseSuyo=true;
		}else if(ultimoPaseSuyo){
			ultimoPaseMio=false;
		}
		if(sp.puedenRematar().length>0){
			ultimoPaseMio=true;
			ultimoPaseSuyo=false;
		}
		Posicion[] posicion = Posiciones.standar;
		JugadorProImplementation[] jugadorDetalles = JugadorProImplementationFactory
				.getJugadores();
		Posicion posicionObjetivo = null;
		for (int jugador = 1; jugador < posicion.length; jugador++) {
			posicionObjetivo = posicionLimitada(posicion[jugador], sp
					.misJugadores()[jugador], jugadorDetalles[jugador], sp);// (posicion[cont],cont),posicionY(posicion[cont].getY(),cont));
			comandos.add(new ComandoIrA(jugador, posicionObjetivo));
		}
		/*if(ultimoPaseMio){
			for (int jugador = 8; jugador < posicion.length; jugador++) {
				comandos.add(new ComandoIrA(jugador, Posiciones.standar[jugador]));
			}
		}*/
		posicionPortero(sp, comandos);
		int jugadorMasCercanoAlBalon = 0;
		double distancia = 1000;
		for (int jugador = 0; jugador < sp.misJugadores().length; jugador++) {
			if (sp.misJugadores()[jugador].distancia(sp.balon()) < distancia) {
				distancia = sp.misJugadores()[jugador].distancia(sp.balon());
				jugadorMasCercanoAlBalon = jugador;
			}
		}
		comandos.add(new ComandoIrA(jugadorMasCercanoAlBalon, sp.balon()));

	}

	public static Posicion posicionLimitada(Posicion posicionInicial,
			Posicion posicionActual, JugadorProImplementation jugador,
			SituacionPartido sp) {
		Posicion pbalon = sp.balon();
		double diferenciaX = pbalon.getX() - posicionActual.getX();
		double diferenciaY = pbalon.getY() - posicionActual.getY();
		double x = posicionActual.getX() + diferenciaX;
		double y = posicionActual.getY() + diferenciaY;
		if (pbalon.getX() > posicionInicial.getX() + jugador.getMaxLateral()) {
			x = posicionInicial.getX() + jugador.getMaxLateral();
		} else if (pbalon.getX() < posicionInicial.getX()
				- jugador.getMaxLateral()) {
			x = posicionInicial.getX() - jugador.getMaxLateral();
		}
		if (y > posicionInicial.getY() + jugador.getMaxSubida()) {
			y = posicionInicial.getY() + jugador.getMaxSubida();
		} else if (y < posicionInicial.getY() + jugador.getMaxBajada()) {
			y = posicionInicial.getY() + jugador.getMaxBajada();
		}
		return new Posicion(x, y);
	}

	public static void posicionPortero(SituacionPartido sp, List<Comando> comandos) {
		Posicion posicion=Posicion.Interseccion(sp.balon(), Constantes.centroArcoInf, new Posicion(Constantes.posteDerArcoInf.getX(),Constantes.posteDerArcoInf.getY()+3), new Posicion(Constantes.posteIzqArcoInf.getX(),Constantes.posteIzqArcoInf.getY()+3));//findLineSegmentIntersection(sp.balon().getX(), sp.balon().getY(), Constantes.centroArcoInf.getX(), Constantes.centroArcoInf.getY(), Constantes.posteDerArcoInf.getX(), Constantes.posteDerArcoInf.getY()+3, Constantes.posteIzqArcoInf.getX(), Constantes.posteIzqArcoInf.getY()+3);
		comandos.add(new ComandoIrA(0,new Posicion(posicion.getX(),Constantes.centroArcoInf.getY()+3)));
	}

	
	public static Posicion findLineSegmentIntersection(double x0, double y0,
			double x1, double y1, double x2, double y2, double x3, double y3) {
		final double LIMIT = 1e-5;
		final double INFINITY = 1e10;
		double x, y;
		double a0 = equals(x0, x1, LIMIT) ? INFINITY : (y0 - y1)
				/ (x0 - x1);
		double a1 = equals(x2, x3, LIMIT) ? INFINITY : (y2 - y3)
				/ (x2 - x3);
		double b0 = y0 - a0 * x0;
		double b1 = y2 - a1 * x2;
		if (equals(a0, a1)) {
			if (!equals(b0, b1))
				return new Posicion(Constantes.centroArcoInf); // Parallell non-overlapping
			else {
				if (equals(x0, x1)) {
					if (Math.min(y0, y1) < Math.max(y2, y3)
							|| Math.max(y0, y1) > Math.min(y2, y3)) {
						double twoMiddle = y0 + y1 + y2 + y3
								- min(y0, y1, y2, y3)
								- max(y0, y1, y2, y3);
						y = (twoMiddle) / 2.0;
						x = (y - b0) / a0;
					} else
						return new Posicion(Constantes.centroArcoInf);
				} else {
					if (Math.min(x0, x1) < Math.max(x2, x3)
							|| Math.max(x0, x1) > Math.min(x2, x3)) {
						double twoMiddle = x0 + x1 + x2 + x3
								- min(x0, x1, x2, x3)
								- max(x0, x1, x2, x3);
						x = (twoMiddle) / 2.0;
						y = a0 * x + b0;
					} else
						return new Posicion(Constantes.centroArcoInf);
				}
				return new Posicion(x,y);
				
			}
		}

		// Find correct intersection point
		if (equals(a0, INFINITY)) {
			x = x0;
			y = a1 * x + b1;
		} else if (equals(a1, INFINITY)) {
			x = x2;
			y = a0 * x + b0;
		} else {
			x = -(b0 - b1) / (a0 - a1);
			y = a0 * x + b0;
		}
		Posicion posicion=new Posicion(x,y);
		

		// Then check if intersection is within line segments
		double distanceFrom1;
		if (equals(x0, x1)) {
			if (y0 < y1)
				distanceFrom1 = y < y0 ? length(x, y, x0, y0)
						: y > y1 ? length(x, y, x1, y1) : 0.0;
			else
				distanceFrom1 = y < y1 ? length(x, y, x1, y1)
						: y > y0 ? length(x, y, x0, y0) : 0.0;
		} else {
			if (x0 < x1)
				distanceFrom1 = x < x0 ? length(x, y, x0, y0)
						: x > x1 ? length(x, y, x1, y1) : 0.0;
			else
				distanceFrom1 = x < x1 ? length(x, y, x1, y1)
						: x > x0 ? length(x, y, x0, y0) : 0.0;
		}

		double distanceFrom2;
		if (equals(x2, x3)) {
			if (y2 < y3)
				distanceFrom2 = y < y2 ? length(x, y, x2, y2)
						: y > y3 ? length(x, y, x3, y3) : 0.0;
			else
				distanceFrom2 = y < y3 ? length(x, y, x3, y3)
						: y > y2 ? length(x, y, x2, y2) : 0.0;
		} else {
			if (x2 < x3)
				distanceFrom2 = x < x2 ? length(x, y, x2, y2)
						: x > x3 ? length(x, y, x3, y3) : 0.0;
			else
				distanceFrom2 = x < x3 ? length(x, y, x3, y3)
						: x > x2 ? length(x, y, x2, y2) : 0.0;
		}

		return posicion;
	}
	
	private static boolean equals (double a, double b, double limit)
	  {
	    return Math.abs (a - b) < limit;
	  }
  private static boolean equals (double a, double b)
	  {
	    return equals (a, b, 1.0e-5);
	  }
	  
  public static double length (double[] v)
	  {
	    return Math.sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
	  }
	  public static double length (int x0, int y0, int x1, int y1)
	  {
	    return length ((double) x0, (double) y0,
	                            (double) x1, (double) y1);
	  }
	  public static double length (double x0, double y0, double x1, double y1)
	  {
	    double dx = x1 - x0;
	    double dy = y1 - y0;
	  
	    return Math.sqrt (dx*dx + dy*dy);
	  }
	  public static double length (int[] x, int[] y, boolean isClosed)
	  {
	    double length = 0.0;

	    int nPoints = x.length;
	    for (int i = 0; i < nPoints-1; i++)
	      length += length (x[i], y[i], x[i+1], y[i+1]);

	    // Add last leg if this is a polygon
	    if (isClosed && nPoints > 1)
	      length += length (x[nPoints-1], y[nPoints-1], x[0], y[0]);

	    return length;
	  }
	  
	  private static double min (double a, double b, double c, double d)
	  {
	    return Math.min (Math.min (a, b), Math.min (c, d));
	  }
	  private static double max (double a, double b, double c, double d)
	  {
	    return Math.max (Math.max (a, b), Math.max (c, d));
	  }
}
